<?php

class perfilPermissions extends Object{
    
    private   $action_name         = "";
    private   $getPermissionString = "";
    private   $update_permissions  = "";
    private   $cod_perfil          = "";
    protected $uobj                = null;
    protected $act                 = null;
    protected $acc                 = null;
    protected $perm                = null;
    protected $db                  = null;
    private   $cookie_perm         = "usuario_perm";
    private   $cookie              = "usuario_permissoes";
    
    public function __construct() {
        $this->LoadModel('usuario/login'    , 'uobj');
        $this->LoadModel('plugins/action'   , 'act');
        $this->LoadModel('plugins/acesso'   , 'acc');
        $this->LoadModel('plugins/permissao', 'perm');
        $this->LoadResource('database', 'db');
    }
    
    public function getPerfilPermissions($cod_perfil){
        $this->LoadModel('plugins/acesso', 'acesso');
        $this->db->Join($this->acesso->getTable(), $this->perm->getTable());
        $permissoes = $this->acesso->selecionar(array('plugins_permissao_nome', 'plugins_acesso_permitir'), "usuario_perfil_cod = '$cod_perfil'");
        $out = array();
        foreach($permissoes as $perm)
            $out[$perm['plugins_permissao_nome']] = ($perm['plugins_acesso_permitir'] == "s")?"1":"0";
        return $out;
    }
    
    public function hasPermission(&$action_name, $getPermissionString, $update_permissions){
        
        $this->init($action_name, $getPermissionString, $update_permissions);
        
        //carrega a pemissão
        $permission = $this->loadPermissions();
        
        //se permissão é negativa, verifica se existe alguma pemissão explícita para o usuário
        $bool = true;
        if($permission == "n"){
            $this->LoadModel('usuario/login', 'uobj');
            $bool = ($this->uobj->getCodPerfil() == Webmaster);
            if($bool) $permission = 's';
        }
        return ($this->getPermissionString == false)?$bool:$permission;
    }
    
    public function RedirectIfHasPermission($action_name){
        if($this->hasPermission($action_name)){
            Redirect($action_name);
        }
    }
    
    public function hasPermissionByName($permname){
        $perm = cookie::getVar($this->cookie_perm);
        
        if(empty($perm)){
            $cod_perfil = $this->uobj->getCodPerfil();
            if($cod_perfil != ""){
                $perm = $this->getPerfilPermissions($cod_perfil);
                cookie::setVar($this->cookie_perm, $perm);
            }
        }
        
        if(!is_array($perm))$perm = array();
        
        return(array_key_exists($permname, $perm) && $perm[$permname] == 1);
    }
    
    
    
    
    
    
    private function init($action_name, $getPermissionString, $update_permissions){
        $this->action_name         = $action_name;
        $this->getPermissionString = $getPermissionString;
        $this->update_permissions  = $update_permissions;
        $this->cod_perfil          = $this->uobj->getCodPerfil();
    }
    
    /*
     * Recebe uma string contento Plugin/Subplugin/Action
     * Carrega todas as permissões do usuário em um cookie.
     * Retorna s => caso o usuário possa ver todos os dados de uma action
     *         n => caso o usuário não possa ver nada naquela action
     *         p => caso o usuário possa ver apenas os próprios dados
     */
    private function loadPermissions(){
        
        //verifica se existe alguma atualização nas permissões do usuário
        if($this->update_permissions){
            cookie::destroy($this->cookie_perm);
            $this->uobj->isUpdatedPermissions();
        }
        
        //verifica se o usuário foi bloquado no sistema
        if($this->uobj->isBloqued()){
            throw new AcessDeniedException("O seu acesso ao sistema foi bloqueado por um administrador");
        }
        
        //cria os cookies
        $this->genCookies();
        
        //corrige o nome da ação caso tenha algum caractere inválido
        $this->prepare_action();
        
        //recupera o cookie gravado
        $perm = cookie::getVar($this->cookie);
        
        //se ação não existe, então ela é proibida
        if(!array_key_exists($this->action_name, $perm)) return "n";
        return $perm[$this->action_name];
    }
    
    //usado em loadPermissions para gerar os cookies
    private function genCookies(){
        
        //cria os cookies caso nao exista
        if(!cookie::cookieExists($this->cookie_perm) || cookie::getVar($this->cookie_perm) == ""){
            if($this->cod_perfil != ""){
                $perm = $this->getPerfilPermissions($this->cod_perfil);
                cookie::setVar($this->cookie_perm, $perm);
            }
        }
        if(!cookie::cookieExists($this->cookie) || cookie::getVar($this->cookie) == ""){
            if($this->cod_perfil != "") $this->LoadLoggedPermissions();
            else                  $this->LoadUnloggedPermissions();
        }
    }
    
    
    //usado em loadPermissions para corrigir o nome da ação
    private function prepare_action(){
        //a ação deve conter o caminho completo
        $exp = explode('/', $this->action_name);
        foreach($exp as $cod => $e){
            $exp[$cod] = str_replace('/', '', trim($e));
            if(trim($e) == "") unset($exp[$cod]);
        }
        
        $count = count($exp);
        if($count < 3){
            if($count == 0) return "s";
            $this->action_name = ($count == 1)? "$this->action_name/index/index":"$this->action_name/index";
        }elseif($count > 3) $this->action_name = @$exp[0]."/".@$exp[1]."/".@$exp[2]." ";
        $this->action_name = str_replace(array('//', "/ "), array('/', ""), trim($this->action_name));
        if($this->action_name[strlen($this->action_name)-1] == "/") {
            $this->action_name[strlen($this->action_name)-1] = "";
            $this->action_name = trim($this->action_name);
        }
    }
    
    
    /*
     * Carrega as permissões para usuários que autenticados no sistema
     */
    private function LoadLoggedPermissions(){
        
        $this->db->Join($this->act->getTable(), $this->perm->getTable());
        $this->db->Join($this->perm->getTable(), $this->acc->getTable());
        $permissions = $this->act->selecionar(array(
            'plugins_permissao_label', 'plugins_action_nome', 
            'plugins_acesso_permitir', 'plugins_action_groupyes',
            'plugins_action_groupno' , 'plugins_action_privacidade',
        ), "usuario_perfil_cod = '$this->cod_perfil'");
        
        $arr = $this->LoadUnloggedPermissions();
        if(empty($permissions)) {
            cookie::setVar($this->cookie, $arr);
            return;
        }
        
        foreach($permissions as $perm){                

            //permissão inicial é vazia
            $permissao = "";

            //se ação é privada checa as permissões
            if($perm['plugins_action_privacidade'] == 'privado'){

                //se ação é permitida, verifica a permissão no grupo de permitidos
                if    ($perm['plugins_acesso_permitir'] == 's')  $permissao = $perm['plugins_action_groupyes'];

                //se ação não é permitida, verifica a permissão no grupo de não permitidas
                elseif($perm['plugins_acesso_permitir'] == 'n')  $permissao = $perm['plugins_action_groupno'];

                //se não é nem permitida nem bloqueada há algum erro e lança execeção
                else  throw new modelException("A permissão ".$perm['plugins_permissao_label'] . " não foi definida
                    nem como permitida nem como bloqueada! Provável erro na instalação do script");
            }

            //se ação é pública, então é permitido
            else $permissao = "s";
            $arr[$perm['plugins_action_nome']] = $permissao;
        }
        
        //salva a permissão em um cookie
        cookie::setVar($this->cookie, $arr);
    }
    
    
    /*
     * Carrega as permissões para usuários que não estão logados
     */
    private function LoadUnloggedPermissions(){
        $arr = array();
        
        $permissions = $this->act->selecionar(array('plugins_action_nome', 'plugins_action_privacidade'));
        foreach($permissions as $perm){    
            $permissao = ($perm['plugins_action_privacidade'] == 'privado')?"n":"s";
            $arr[$perm['plugins_action_nome']] = $permissao;
        }
        cookie::setVar($this->cookie, $arr);
        return $arr;
    }
    
}

?>